package com.education.common.config;

import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.fastjson.JSONObject;
import com.education.common.utils.ApiReturnObject;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * 全局异常处理器
 *
 * @author liftsail
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 捕获ExcelAnalysisException异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = ExcelAnalysisException.class)
    public ApiReturnObject processExcetion2(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Exception e) {
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof ExcelAnalysisException) {
            return new ApiReturnObject("201", e.getMessage(), "");
        }
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), "当前服务器正忙，请稍后重试");
    }

    /**
     * 捕获ExpiredJwtException异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = ExpiredJwtException.class)
    public ApiReturnObject processExcetion3(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Exception e) {
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof ExpiredJwtException) {
            return new ApiReturnObject("401", e.getMessage(), "token已过期,请重新登录！");
        }
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), "当前服务器正忙，请稍后重试");
    }

    /**
     * 捕获IllegalArgumentException异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public ApiReturnObject processExcetion4(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Exception e) {
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof IllegalArgumentException) {
            return new ApiReturnObject("201", e.getMessage(), "非法参数异常!");
        }
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), "当前服务器正忙，请稍后重试");
    }

    /**
     * 捕获JwtException异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = JwtException.class)
    public ApiReturnObject processExcetion5(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Exception e) {
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof JwtException) {
            return new ApiReturnObject("201", e.getMessage(), "jwt token 发生异常，请检查请求头!");
        }
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), "当前服务器正忙，请稍后重试");
    }

    /**
     * 捕获ValidationException异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = ValidationException.class)
    public ApiReturnObject processExcetion6(HttpServletRequest request,
                                            HttpServletResponse response,
                                            Exception e) {
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof ValidationException) {
            return new ApiReturnObject("201", e.getMessage(), "参数发生异常，请检查传参!");
        }
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), "当前服务器正忙，请稍后重试");
    }

    /**
     * 参数为实体类
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiReturnObject handleValidException(HttpServletRequest req, MethodArgumentNotValidException e) {
        JSONObject json = new JSONObject();
        json.put("path", req.getRequestURI());
        String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
        json.put("code", 400);
        json.put("success", false);
        json.put("msg", defaultMessage);
        json.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        return new ApiReturnObject("201", defaultMessage, json);
    }

    /**
     * 参数为单个参数或多个参数
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ApiReturnObject handleConstraintViolationException(HttpServletRequest req, ConstraintViolationException e) {
        //获取参数校验异常message
        String message = e.getLocalizedMessage().split(": ")[1];
        JSONObject json = new JSONObject();
        json.put("path", req.getRequestURI());
        json.put("code", 400);
        json.put("success", false);
        json.put("msg", message);
        return new ApiReturnObject("201", message, json);
    }

    /**
     * 普通的参数传递的形式;
     *
     * @param req
     * @param exception
     * @return
     * @throws Exception
     * @author khy
     * @createTime 2021年5月18日下午5:25:16
     */
    @ExceptionHandler(value = BindException.class)
    public ApiReturnObject validatedGetException(HttpServletRequest req, BindException exception) {
        JSONObject json = new JSONObject();
        json.put("path", req.getRequestURI());
        String defaultMessage = exception.getBindingResult().getFieldError().getDefaultMessage();
        json.put("code", 400);
        json.put("success", false);
        json.put("msg", defaultMessage);
        json.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        return new ApiReturnObject("201", defaultMessage, json);
    }

    /**
     * 捕获Exception异常
     *
     * @param request
     * @param response
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ApiReturnObject processExcetion(HttpServletRequest request,
                                           HttpServletResponse response,
                                           Exception e) {
        //解析异常信息
        //如果是系统自定义异常，直接取出errCode和errMessage
        if (e instanceof BusinessException) {
            LOGGER.info(e.getMessage(), e);
            //解析系统自定义异常信息
            BusinessException businessException = (BusinessException) e;
            ErrorCode errorCode = businessException.getErrorCode();
            if (errorCode != null) {
                //错误代码
                int code = errorCode.getCode();
                //错误信息
                String desc = errorCode.getDesc();
                return new ApiReturnObject(String.valueOf(code), desc, "此异常为自定义异常 请仔细查看message报错信息 进行对应操作");
            }
            return new ApiReturnObject(businessException.getCode() + "", businessException.getMessage(), "");
        }
        LOGGER.error("系统异常：", e);
        //统一定义为99999系统未知错误
        return new ApiReturnObject(String.valueOf(CommonErrorCode.UNKOWN.getCode()), CommonErrorCode.UNKOWN.getDesc(), e.getMessage());
    }

}
